• Friday, October 4, 2024

    Sahil Lavingia, the CEO of Gumroad, shared insights on the decision-making process regarding the technology stack for a new project called Helper. Initially, there was optimism about using htmx, a framework designed to simplify interactions in web applications. Lavingia's enthusiasm was influenced by past experiences with React, which he felt was often too complex for their needs. He believed htmx could provide a lightweight alternative for adding simple interactions. However, as the project progressed, the team encountered several challenges that led them to abandon htmx in favor of React and Next.js. One of the primary issues was the developer experience; while htmx could technically accomplish their goals, the process felt forced and less intuitive compared to the natural flow they experienced with Next.js. This was particularly evident when building complex forms that required dynamic validation and conditional fields, where htmx necessitated convoluted server-side logic. User experience also suffered with htmx, as it tended to push the application towards a Rails/CRUD approach, resulting in a generic and uninspiring interface. The team faced significant hurdles when trying to implement features like drag-and-drop functionality, which was much smoother and more efficient with React libraries. Another factor was the support from AI tools, which were more familiar with Next.js than htmx. This discrepancy affected their development speed and problem-solving capabilities, as resources for React/Next.js were more abundant and accessible. As the project grew in complexity, htmx's limitations became more pronounced. The simplicity that initially attracted the team began to feel restrictive, especially when they needed to implement sophisticated interactions and manage state across multiple components. The vast ecosystem surrounding React and Next.js provided solutions to many challenges, whereas htmx often required the team to create custom solutions or compromise on functionality. Ultimately, the transition to React and Next.js allowed Gumroad to enhance the user experience significantly. Features like drag-and-drop functionality, complex state management, dynamic form generation, and real-time collaboration were easier to implement and optimize within the React ecosystem. The team found that React's tools and libraries facilitated a more engaging and responsive application. Lavingia concluded that while htmx has its merits, particularly for simpler projects or those built on existing server-rendered applications, the specific needs of the Helper project made React and Next.js the better choice. He acknowledged the importance of selecting technologies that can grow with a project and support long-term goals. The experience reinforced the idea that understanding a project's unique requirements is crucial in choosing the right tools, and he remains open to reevaluating their tech stack as needs evolve and new technologies emerge.

  • Monday, June 3, 2024

    htmx offers a simpler alternative to frameworks in frontend development by enhancing HTML with attributes that enable AJAX-like functionality, utilizing the hypermedia concept to create RESTful applications without excessive JavaScript.

  • Wednesday, September 11, 2024

    This developer built the same web application using different web frameworks: FastAPI, FastHTML, Next.js, SvelteKit, and FastAPI combined with Svelte. They compared the developer experience and unique features of each framework by implementing CRUD operations in a simple "Look at Your Data" app. FastAPI and FastHTML were more concise in code, while Next.js and SvelteKit required more code but offered a more structured approach and better UI elements.

  • Monday, April 29, 2024

    Web development started with simple HTML and CSS. Eventually, client-side JavaScript allowed for more dynamic websites. The need for SEO and performance led to the creation of server-side rendering and frameworks like Next.js. JavaScript's shortcomings led to TypeScript and Svelte. At the end of the day, the core goal of all these evolutions was to create enjoyable user experiences, so the tools being used don't matter much.

  • Friday, June 28, 2024

    Front-end development has become unnecessarily complex due to poor choices, such as over-reliance on JavaScript frameworks and ignoring fundamental principles like content importance and CSS capabilities. This complexity leads to frustration and inefficiency. Developers should prioritize simplicity.

  • Tuesday, August 20, 2024

    After using TanStack Router in production for eight months, this author believes in organizing code into vertical modules, using loaders for page-level data and suspense queries for component-specific data, and avoiding premature code generalization. He promotes a “go gardening approach” that involves abstracting code only when clear patterns show up.

  • Thursday, May 9, 2024

    This author rewrote their novel-writing app, Fablehenge, from React to Svelte because Svelte offered faster development, less code, and a more enjoyable experience. Svelte's challenges include styling child components and Svelte 4's reactivity model. The author believes Svelte's advantages outweigh these and that Svelte could become the leading framework for new projects.

    Md Impact
  • Friday, March 15, 2024

    This is a thorough comparison of the template languages used by React, Vue, Angular, and Svelte. It looks at how the frameworks define and use components, event handling, and more advanced techniques like slotting. While all four frameworks can do everything that was tested, React still feels most natural to the author.

  • Friday, August 2, 2024

    React introduced the concept of a "virtual DOM" to optimize web app rendering. Its popularity led to widespread adoption, but also to criticisms regarding its learning curve, state management, and performance. While React's defenders highlight its improvements in recent versions, alternative frameworks like Svelte and Astro offer simpler approaches without relying on the virtual DOM.

  • Friday, August 16, 2024

    Daniel Beck, a seasoned developer, shares his personal experiences with XSLT, inefficient database connections, and disastrous refactoring efforts. His experience with horrific codebase complexity only reinforced how hard it can be to rectify human errors.

  • Monday, July 22, 2024

    Does shipping digital experiences quickly mean compromising on quality? Not necessarily. AI and visual development create new ways to build, iterate upon, and optimize applications and websites. This live session will cut through the hype and provide a realistic view of how traditional CMS architecture misses the mark and how emerging technologies address long-standing challenges: > How visual development + AI can dramatically accelerate your workflow > The power of Generative UI and Structured UI in modern web development > Real-world examples of organizations shipping digital experiences 10x faster

  • Friday, September 6, 2024

    In benchmarks of server-side rendering (SSR) across frontend frameworks, like React, Vue, Svelte, and Solid, fastify-html and Vue are the top performers. Svelte and Solid are close behind, while React and Preact are significantly slower. As a result, Vue and Svelte provide the best balance of SSR performance and ecosystem maturity.

    Hi Impact
  • Friday, May 24, 2024

    This author initially designed a strict, composable design system inspired by Chakra UI to solve inconsistencies and a poorly structured existing design system. However, the system proved difficult for many developers to use due to their lack of experience with functional composition. In hindsight, the author believes a design system built around Tailwind/NativeWind would have been more approachable for developers.

  • Tuesday, June 4, 2024

    The creator of Ruby on Rails, David Heinemeier Hansson, realized that the success of the framework was not due to his attempts to convince others, but rather by showcasing its capabilities and letting others decide for themselves. He now believes in respecting the various preferences of programmers and encouraging them to find the language that best suits their individual style and needs.

  • Thursday, September 5, 2024

    This is an open-source starter kit for building production-ready SaaS applications. It uses a curated stack of tools, including Next.js, Supabase, and TailwindCSS, organized as a monorepo with a focus on code reuse and best practices.

  • Tuesday, April 16, 2024

    React Server Components (RSCs) allow server-exclusive code, which can lead to better performance. However, this means that popular styling options, like CSS-in-JS libraries which rely on React's lifecycle, can conflict with RSCs. RSC's server-side focus clashes with the browser-centric nature of traditional CSS-in-JS libraries, but there are “zero-runtime” CSS-in-JS libraries that are fully compatible with RSCs today. If your application doesn't use these and already has a good “time-to-interactive” time, then migrating to these libraries is not worth it.

  • Tuesday, July 2, 2024

    A paradigm shift is happening towards simpler web development that utilizes built-in browser APIs. While this shift promises better performance and cost savings, it requires a skill set that many organizations and developers lack. LLMs are being used as a workaround, but they are not well-suited to this new shift due to a lack of relevant training data.

  • Friday, May 10, 2024

    CodeHelium is a React editor component that compiles, executes, and returns the outputs of any user-written Python code using WebAssembly.

  • Thursday, August 15, 2024

    This author, a solo developer, shares his experience building a chatbot builder called Fastmind. He used React for the frontend, Hono for the backend, and Convex for the database. The architecture has separate frontend applications for the chatbot builder, chat widget, and marketing website.

    Hi Impact
  • Thursday, May 30, 2024

    Design system experts from Bumble, GitHub, and HP discuss leveraging the new Code Connect feature to integrate design and code, highlighting the importance of a shared language and seamless workflow. They emphasize the need for continuous collaboration and the adoption of best practices to maximize the utility of design systems, ensuring consistency and reducing friction between designers and developers.

  • Wednesday, October 2, 2024

    In the realm of frontend development, effective testing is crucial for maintaining high-quality software. Quentin Spencer-Harper, drawing from his extensive experience at Palantir, shares insights gained from managing a significant frontend codebase composed of over a million lines of TypeScript. His reflections highlight the importance of a well-structured testing strategy, emphasizing that the right approach to testing can dramatically enhance engineering velocity. Spencer-Harper identifies three key lessons learned over a decade of experience. First, he underscores that while there are various factors contributing to frontend stability, this discussion will focus specifically on testing. He argues that investing in testing is unique in its potential to double engineering velocity, unlike other improvements that tend to yield only incremental gains. The ability to make changes with confidence allows developers to iterate quickly and refactor code without fear, which is essential for maintaining a healthy codebase. However, he notes a common pitfall: many automated frontend tests can inadvertently slow teams down due to the time required for their creation and maintenance. To counter this, he advocates for a thoughtful testing strategy that minimizes maintenance costs. The maintenance cost of tests is a critical determinant of their long-term value; reducing this cost can exponentially increase the number of tests a team can afford, thereby enhancing overall coverage and effectiveness. Spencer-Harper presents two strategies to manage maintenance costs effectively. The first involves designing tests that are quick to update, allowing developers to swiftly determine whether a change is expected or requires adjustment. The second strategy focuses on testing at the minimal cut, meaning that tests should encompass the smallest necessary scope to ensure stability while avoiding excessive fragility from mocked APIs. He elaborates on the importance of defining the scope of tests carefully. For instance, unit tests should not be overly granular; instead, they should test logical groupings of functionality that reflect the complexity of the application. This approach helps maintain test relevance and reduces the frequency of required updates. Additionally, he advises against writing component tests for React applications, as they often prove to be slow and fragile. Instead, he suggests focusing on testing utility functions that encapsulate complex logic, which can be more stable and easier to maintain. Integration tests should be strategically designed to align with stable APIs, allowing for easy addition of new tests without incurring high maintenance costs. Spencer-Harper cites examples from successful applications, such as MapboxGL, where the testing structure is built around stable API formats, enabling efficient test management. Ultimately, he emphasizes that while traditional testing methods can enhance team performance, they may not suffice to achieve the highest levels of engineering velocity. To truly excel, teams should consider automated solutions that leverage real user interactions to create comprehensive test suites. Meticulous AI is highlighted as a tool that captures user flows and generates a visual snapshot test suite, allowing for near-complete coverage of the codebase without the burden of manual test maintenance. In conclusion, Spencer-Harper's insights advocate for a strategic approach to frontend testing that prioritizes maintenance efficiency and effective coverage. By focusing on the right testing practices and leveraging automation, development teams can enhance their velocity and maintain high-quality software.

  • Friday, July 5, 2024

    Next.js needed a new bundler due to the limitations of Webpack in handling large-scale applications, particularly with the increasing use of component libraries and the rise of computationally heavy applications. The new bundler, Turbopack, aims to provide faster HMR and initial compile times, maintain compatibility with existing applications, and scale effectively for large codebases. It will also incorporate persistent caching and production optimizations.

  • Thursday, September 26, 2024

    The blog post discusses the concept of component composition in React, emphasizing its significance as a core advantage of the framework. Initially, the author reflects on their early experiences with React, highlighting features like the Virtual DOM, one-way data flow, and JSX. However, they argue that the true strength of React lies in its ability to compose components into more complex structures, a practice that was not widely accepted in software development a decade ago. The author addresses the traditional notion of separation of concerns, suggesting that while it still exists, it has evolved. Instead of separating styles, logic, and markup into distinct layers, React encourages grouping them together within components, leading to better code cohesion. This shift allows developers to think in terms of components, which can enhance the organization and maintainability of code. The discussion then shifts to conditional rendering, a common practice in React where components are rendered based on certain conditions. The author presents an example of a `ShoppingList` component that conditionally renders user information and items based on the presence of data. While this approach is acceptable for simple cases, the author warns that it can become problematic when managing multiple states within a single component. As the complexity of the component increases, the author illustrates how conditional rendering can lead to a convoluted structure that is difficult to read and maintain. They propose breaking down the component into smaller, more manageable pieces, suggesting the use of a layout component to encapsulate shared elements while allowing for dynamic content based on the component's state. The author advocates for using early returns to handle different states of a component more clearly. By returning early for each state (e.g., loading, no data, or displaying data), the code becomes easier to follow and reduces cognitive load. This method also facilitates the addition of new conditions, such as error handling, without complicating the existing logic. The post concludes by emphasizing the importance of component composition and the need to avoid excessive conditional rendering. The author encourages developers to embrace early returns and to continually reassess their component structures to ensure clarity and maintainability. They invite readers to engage with them for further discussion or questions, reinforcing the community aspect of learning and sharing knowledge in the React ecosystem.

  • Tuesday, June 11, 2024

    The most productive solo dev stack is the one that you can code the fastest in.

  • Wednesday, September 25, 2024

    This article goes over a complete frontend redesign of a website that involved creating a new header, a unique hero section featuring personalized hats drawn by the author's daughter, and a circular navigation for the hats section. It also incorporated interactive elements using Framer Motion and scroll-driven animations, along with the usage of CSS features like container queries, :has(), offset-path, and more.

  • Friday, September 27, 2024

    In the realm of React development, achieving better component decoupling is essential for creating maintainable and reusable code. A common scenario involves an onboarding component that transitions through various steps, such as WelcomeStep, TermsOfServiceStep, and CompleteStep. A typical implementation might involve a state variable to track the current step and pass a state setter function down to child components. While this approach works, it introduces tight coupling between the parent and child components, which can lead to several issues. The tight coupling arises because the child components gain direct access to the parent's internal state management. This can break encapsulation, making it difficult to troubleshoot issues since the parent loses control over how its state is modified. If a child component can change the parent's state in unexpected ways, it complicates debugging and can lead to unintended side effects. Additionally, this setup can result in unnecessary re-renders, as the child components dictate when the parent should update its state, rather than the parent controlling its own updates. To address these concerns, a more effective solution is to have the child components provide callback functions to the parent. This approach allows the parent to maintain control over its state while still enabling the child components to signal when an action should occur. For instance, instead of passing a setter function directly, the parent can pass a callback like `onClickNext`, which the child can invoke when it needs to trigger a state change. This method not only reduces coupling but also enhances the reusability and testability of the child components. A practical example of this revised approach can be seen in the updated implementation of the onboarding component. The parent component retains the state management but now calls the setter function within its own context, using the callback provided by the child. This design allows for more complex logic to be incorporated into the callback if needed, while also simplifying the interface of the child components. When designing components, it is crucial to consider their interfaces carefully. By thinking of components in isolation, developers can create simpler, more intuitive, and reusable components that are easier to test. This focus on decoupling and interface design ultimately leads to a more robust and maintainable codebase, enhancing the overall development experience in React.

  • Friday, August 2, 2024

    Incident.io chose React Native for its on-call mobile app because it could provide a native feel, a single codebase for iOS and Android, and code familiarity for its team. The team initially used Expo Go for rapid development and iteration during a hackathon, then transitioned to the "managed workflow" setup for production, using Expo's build services and implementing native features through Expo's "modules" system.

  • Tuesday, October 1, 2024

    In today's technology landscape, there is an overwhelming abundance of frameworks, libraries, and plugins that promise to streamline development and reduce costs. Many businesses eagerly adopt these external codebases, hoping to accelerate their time to market. However, a significant number of developers overlook the hidden costs and risks associated with relying on these external solutions. One of the most critical considerations is security. Regardless of whether the code was written in-house or sourced externally, the responsibility for every line of code in a project ultimately falls on the organization. The consequences of a security breach are severe, whether the vulnerability lies in an external library or internal code. While external codebases may seem appealing, they often introduce a larger attack surface, making it easier for malicious actors to exploit vulnerabilities. In contrast, internally developed code tends to be more focused and task-specific, which can significantly reduce security risks. Dependency on external codebases can create substantial risks throughout a project's lifecycle. Many libraries have their own dependencies, leading to complex dependency graphs that can complicate maintenance and increase vulnerability exposure. Even after thorough research to select an appropriate library, the landscape can change rapidly. A library that seemed suitable six months ago may no longer be actively maintained or may undergo significant changes that require ongoing integration work. This can lead to a cycle of dependency management that consumes valuable resources. Moreover, the notion that free libraries come without cost is misleading. Organizations must account for the time and effort spent on researching, evaluating, integrating, and maintaining these external codebases. When comparing the total cost of using an external library to developing a targeted internal solution, it often becomes evident that the latter is more cost-effective in the long run. In building BotBarrier, the team prioritized minimizing dependencies to only those essential functions that could not be developed in-house. This approach allows for greater control over the product and reduces the burden of managing unnecessary dependencies. By opting to create their own backend and frontend frameworks, the team limited their reliance on external libraries, using only three essential SDKs for specific functionalities. Ultimately, the goal is to maintain the flexibility to adapt and innovate without being tethered to the latest trends in technology. Organizations should strive to make informed decisions about their dependencies, focusing on what they can control and ensuring that their development efforts align with their business objectives. By doing so, they can safeguard their projects against the risks associated with external codebases while fostering a more secure and efficient development environment.

  • Wednesday, July 31, 2024

    While using useEffect for data fetching is common, it can lead to several issues, including race conditions, out-of-order responses, and inconsistent UI states. Remix's loader function, which provides built-in request cancellation, race condition prevention, and a smooth user experience, handles data fetching seamlessly. It also allows for custom loading states and provides flexibility and control over the user interface. Remix also has pre-rendering capabilities that deliver pre-rendered HTML with data included.

  • Tuesday, May 28, 2024

    This article presents a way to implement React-like component-based frontend development in Go using the standard library. Its approach defines components using the define function, composes them using templates, and manages state using URL query parameters.